#include "main.h"
#include "stdio.h"

void SystemClock_Config(void);
static void MX_GPIO_Init(void);

// 摩尔斯码时间（ms）
#define DOT_DURATION     1000
#define DASH_DURATION    (DOT_DURATION * 3)
#define SYMBOL_SPACE     DOT_DURATION
#define LETTER_SPACE     (DOT_DURATION * 3)
#define WORD_SPACE       (DOT_DURATION * 7)

// 呼吸灯平滑步数
#define BREATH_STEPS 5

// 函数声明
void morse_dot(void);
void morse_dash(void);
void morse_send(const char *text);
void breathe_led_smooth(uint32_t duration);

// ==============================
// main
// ==============================
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();

    while (1)
    {
        morse_send("SOS"); // 示例摩尔斯电码
        HAL_Delay(WORD_SPACE); // 单词间隔
    }
}

// ==============================
// 平滑呼吸灯函数
// duration: 点或划总时长（ms）
// ==============================
void breathe_led_smooth(uint32_t duration)
{
    uint32_t step_delay = duration / (2 * BREATH_STEPS); // 渐亮+渐暗
    for(int i=0; i<BREATH_STEPS; i++)
    {
        // 渐亮阶段
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
        HAL_Delay(step_delay);  // 保持时间
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
        HAL_Delay(step_delay);
    }
    for(int i=BREATH_STEPS; i>0; i--)
    {
        // 渐暗阶段
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
        HAL_Delay(step_delay);
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
        HAL_Delay(step_delay);
    }
}

// ==============================
// 摩尔斯点/划
// ==============================
void morse_dot(void)  { breathe_led_smooth(DOT_DURATION);  HAL_Delay(SYMBOL_SPACE); }
void morse_dash(void) { breathe_led_smooth(DASH_DURATION); HAL_Delay(SYMBOL_SPACE); }

// ==============================
// 摩尔斯码表
// ==============================
typedef struct { char c; const char *morse; } MorseMap;
MorseMap morse_table[] = {
    {'A', ".-"}, {'B', "-..."}, {'C', "-.-."}, {'D', "-.."},
    {'E', "."}, {'F', "..-."}, {'G', "--."}, {'H', "...."},
    {'I', ".."}, {'J', ".---"}, {'K', "-.-"}, {'L', ".-.."},
    {'M', "--"}, {'N', "-."}, {'O', "---"}, {'P', ".--."},
    {'Q', "--.-"}, {'R', ".-."}, {'S', "..."}, {'T', "-"},
    {'U', "..-"}, {'V', "...-"}, {'W', ".--"}, {'X', "-..-"},
    {'Y', "-.--"}, {'Z', "--.."}
};

const char* get_morse(char c)
{
    if(c >= 'a' && c <= 'z') c -= 32; // 转大写
    for(int i=0; i<26; i++)
        if(morse_table[i].c == c) return morse_table[i].morse;
    return "";
}

// ==============================
// 发送摩尔斯字符串
// ==============================
void morse_send(const char *text)
{
    while(*text)
    {
        if(*text == ' ')
        {
            HAL_Delay(WORD_SPACE);
        }
        else
        {
            const char *code = get_morse(*text);
            while(*code)
            {
                if(*code == '.') morse_dot();
                else if(*code == '-') morse_dash();
                code++;
            }
            HAL_Delay(LETTER_SPACE - SYMBOL_SPACE); // 字母间隔
        }
        text++;
    }
}

// ==============================
// GPIO 初始化
// ==============================
static void MX_GPIO_Init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
}

// ==============================
// 时钟配置
// ==============================
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;

    if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
        Error_Handler();

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|
                                  RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
        Error_Handler();
}

// ==============================
// 错误处理函数
// ==============================
void Error_Handler(void)
{
    while(1)
    {
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4);
        HAL_Delay(200);
    }
}